#ifndef __TGDB_TYPES_H__
#define __TGDB_TYPES_H__

/*! 
 * \file
 * tgdb_types.h
 *
 * \brief
 * This interface is intended to declare and document the ADT's that TGDB 
 * exports to the front ends.
 *
 * The front end can interrogate these data structures to discover what TGDB
 * knows about the debugger. This is currently the only way the front end gets
 * any information about the current debugging session.
 */

#ifdef __cplusplus
extern "C"
{
#endif

#include "tgdb_list.h"

	/* A reference to a command that has been created by TGDB */
	struct tgdb_command;
	struct tgdb_response;

	/******************************************************************************/
	/**
	 * @name Utilitly commands to run on a command.
	 * These functions take a 'struct tgdb_response' as a parameter.
	 */
	/******************************************************************************/

	/*@{*/

	/**
	 * This will print a client generated command to stderr.
	 * These are the commands that are returned to the front end.
	 * It is currently used for debugging purposes.
	 *
	 * \param command
	 * The command to print. It should be of type 'struct tgdb_response'
	 *
	 * @return
	 * Will return -1 if the print command failed. Otherwise, 0.
	 */
	int tgdb_types_print_command (void *command);

	/**
	 * This will free a client generated command.
	 * These are the commands that are returned to the front end.
	 *
	 * \param command
	 * The command to print. It should be of type 'struct tgdb_response'
	 * 
	 * @return
	 * Will return -1 if free'ing failed. Otherwise, 0.
	 */
	int tgdb_types_free_command (void *command);


	/**
	 * This will append a new command into TGDB's queue.
	 *
	 * \param command_list
	 * \param response
	 */
	void tgdb_types_append_command (struct tgdb_list *command_list,
			struct tgdb_response *response);

	enum tgdb_respond_type
	{
		TGDB_COMMON,
		TGDB_CALL_STACK,
		TGDB_DISAS,
		TGDB_THREADS
	};
	/*@}*/

	/**
	 * The client can give any of these commands to TGDB through 
	 * tgdb_run_debugger_command.
	 */
	enum tgdb_command_type
	{

		/** This will instruct TGDB to tell the debugger to continue.  */
		TGDB_CONTINUE = 0,

		/** This will instruct TGDB to tell the debugger to finish.  */
		TGDB_FINISH,

		/** 
		 * This will instruct TGDB to tell the debugger to go to the next 
		 * source level instruction.
		 */
		TGDB_NEXT,

		/** 
		 * This will instruct TGDB to tell the debugger to (re-)start the program. 
		 */
		TGDB_START,

		/** 
		 * This will instruct TGDB to tell the debugger to (re-)run the program.
		 */
		TGDB_RUN,

		/** 
		 * This will instruct TGDB to tell the debugger to kill the program.
		 */
		TGDB_KILL,

		/** This will instruct TGDB to tell the debugger to step.  */
		TGDB_STEP,

		/** This will instruct TGDB to tell the debugger to go up a frame.  */
		TGDB_UP,

		/** This will instruct TGDB to tell the debugger to go down a frame.  */
		TGDB_DOWN,

		TGDB_REQUEST_DISAS,

		TGDB_REQUEST_CALL_STACK,

		TGDB_REQUEST_THREADS,

		TGDB_NEXTI,

		TGDB_STEPI,

		TGDB_SET_THREAD,

		TGDB_SET_FRAME,

		/** 
		 * Hmmm. This is probably bad :). Actually, I can't remember why its here.
		 */
		TGDB_ERROR
	};

	/**
	 * This gives the client the ability to add or remove breakpoints.
	 * Currently, enable/disable are not supported.
	 */
	enum tgdb_breakpoint_action
	{

		/** Add a breakpoint.  */
		TGDB_BREAKPOINT_ADD,

		/** Add a temporary breakpoint */
		TGDB_TBREAKPOINT_ADD,

		/** Delete a breakpoint.  */
		TGDB_BREAKPOINT_DELETE,

		/** Disable a breakpoint.  */
		TGDB_BREAKPOINT_DISABLE,

		/** Enable a breakpoint.  */
		TGDB_BREAKPOINT_ENABLE
	};

	/**
	 * This structure represents a breakpoint.
	 */
	struct tgdb_breakpoint
	{

		/**
		 * This is the file that the breakpoint is set in. This path name can be
		 * relative.
		 */
		char *file;

		/** The name of the function the breakpoint is set at.  */
		char *funcname;

		/** The line number where the breakpoint is set.  */
		int line;

		/** 0 if it is not enabled or 1 if it is enabled.  */
		int enabled;
	};

	/**
	 * This structure currently represents a file position.
	 */
	struct tgdb_file_position
	{

		/** The absolute path to the file.  */
		char *absolute_path;

		/** The relative path to the file.  */
		char *relative_path;

		/** The line number in the file.  */
		int line_number;
	};

	/**
	 * This is used to return a path to the front end.
	 */
	struct tgdb_source_file
	{
		/** The absolute path to the file of interest.  */
		char *absolute_path;
	};

	/**
	 * This tells the front end how the debugger terminated.
	 */
	struct tgdb_debugger_exit_status
	{

		/**
		 * If this is 0, the debugger terminated normally and return_value is valid
		 * If this is -1, the debugger terminated abnormally and return_value is 
		 * invalid
		 */
		int exit_status;

		/**
		 * This is the return value of the debugger upon normal termination.
		 */
		int return_value;
	};

	enum INTERFACE_REQUEST_COMMANDS
	{
		/** Request for TGDB to run a console command through the debugger */
		TGDB_REQUEST_CONSOLE_COMMAND,
		/** 
		 * Request for TGDB to get all of the source files that the debugger 
		 * currently knows about the inferior. */
		TGDB_REQUEST_INFO_SOURCES,
		/**
		 * Request the absolute and relative path from the debugger given a path.
		 * This path being used to get the pair should have been returned by the 
		 * tgdb_request_inferiors_source_files command.
		 */
		TGDB_REQUEST_FILENAME_PAIR,
		/**
		 * This asks TGDB to determine the current fullname, filename and line 
		 * number that the debugger is currently at, in the inferior. */
		TGDB_REQUEST_CURRENT_LOCATION,
		/** Run a debugger command (ie next, step, finish) */
		TGDB_REQUEST_DEBUGGER_COMMAND,
		/** Modify a breakpoint (ie delete/create/disable) */
		TGDB_REQUEST_MODIFY_BREAKPOINT,
		/** Ask GDB to give a list of tab completions for a given string */
		TGDB_REQUEST_COMPLETE,
	};

	struct tgdb_request {
		/** This is the type of request.  */
		enum INTERFACE_REQUEST_COMMANDS header;

		union {
			struct {
				/** The null terminated console command to pass to GDB */
				const char *command;
			} console_command;

			/* info_sources; */

			struct {
				const char *file;
			} filename_pair;

			struct {
				int on_startup;
			} current_location;

			struct {
				/** This is the command that libtgdb should run through the debugger */
				enum tgdb_command_type c;
			} debugger_command;

			struct {
				/* The filename to set the breakpoint in */
				const char *file;
				/* The corresponding line number */
				int line;
				/* The action to take */
				enum tgdb_breakpoint_action b;
			} modify_breakpoint;

			struct {
				/* The line to ask GDB for completions for */
				const char *line;
			} complete;
		} choice;
	};

	typedef struct tgdb_request *tgdb_request_ptr;

	/**
	 *  This is the commands interface used between the front end and TGDB.
	 *  When TGDB is responding to a request or when an event is being generated
	 *  the front end will find out about it through one of these enums.
	 */
	enum INTERFACE_RESPONSE_COMMANDS
	{

		/** All breakpoints that are set.  */
		TGDB_UPDATE_BREAKPOINTS,

		/**
		 * This tells the gui what filename/line number the debugger is on.
		 * It gets generated whenever it changes.
		 * This is a 'struct tgdb_file_position *'.
		 */
		TGDB_UPDATE_FILE_POSITION,

		/**
		 * This returns a list of all the source files that make up the 
		 * inferior program.
		 */
		TGDB_UPDATE_SOURCE_FILES,

		/**
		 * This is a response to the tgdb_get_sources function call.
		 * If the sources can not be recieved you will get this response.
		 */
		TGDB_SOURCES_DENIED,

		/** 
		 * This is a response to the function call tgdb_get_filename_pair.
		 * It returns the absolute and relative path to the source file requested.
		 */
		TGDB_FILENAME_PAIR,

		/** 
		 * This is a response to the function call tgdb_get_source_absolute_filename.
		 * It happens when gdb failed to know what the absolute path to the relative
		 * path asked for was.
		 *
		 * NOTE: If this command is generated and the file is NULL, the command can
		 * be ignored. Currently, the annotate 2 subsytem uses this when trying to
		 * figure out the initial file.
		 */
		TGDB_ABSOLUTE_SOURCE_DENIED,

		/**
		 * This happens when the program being debugged by GDB exits. 
		 * It can be used be the front end to clear any cache that it might have
		 * obtained by debugging the last program. The data represents the exit
		 * status.
		 */
		TGDB_INFERIOR_EXITED,

		/**
		 * This returns a list of all the completions.
		 *
		 */
		TGDB_UPDATE_COMPLETIONS,

		/** The prompt has changed, here is the new value.  */
		TGDB_UPDATE_CONSOLE_PROMPT_VALUE,

		/**
		 * This happens when gdb quits.
		 * libtgdb is done. 
		 * You will get no more responses after this one.
		 * This is a 'struct tgdb_quit_status *'
		 */
		TGDB_QUIT
	};

	/**
	 * A single TGDB response for the front end.
	 * This is the smallest unit of information that TGDB can return to the front 
	 * end.
	 */
	struct tgdb_response
	{
		/** This is the type of response.  */
		enum INTERFACE_RESPONSE_COMMANDS header;

		union {
			/* header == TGDB_UPDATE_BREAKPOINTS */
			struct {
				/* This list has elements of 'struct tgdb_breakpoint *' 
				 * representing each breakpoint. */
				struct tgdb_list *breakpoint_list;
			} update_breakpoints;

			/* header == TGDB_UPDATE_FILE_POSITION */
			struct {
				struct tgdb_file_position *file_position;
			} update_file_position;

			/* header == TGDB_UPDATE_SOURCE_FILES*/
			struct {
				/* This list has elements of 'const char *' representing each 
				 * filename. The filename may be relative or absolute. */
				struct tgdb_list *source_files;
			} update_source_files;

			/* header == TGDB_SOURCES_DENIED */
			/* sources_denied; */

			/* header == TGDB_FILENAME_PAIR */
			struct {
				/** 
				 * If either of these are NULL, the data could not be retrieved from
				 * the debugger. */

				/** The absolute path to the file being looked for */
				const char *absolute_path;
				/** The relative path to the file being looked for */
				const char *relative_path;
			} filename_pair;

			/* header == TGDB_ABSOLUTE_SOURCE_DENIED */
			struct {
				struct tgdb_source_file *source_file;
			} absolute_source_denied;

			/* header == TGDB_INFERIOR_EXITED */
			struct {
				int *exit_status;
			} inferior_exited;

			/* header == TGDB_UPDATE_COMPLETIONS */
			struct {
				/* This list has elements of 'const char *' 
				 * representing each possible completion. */
				struct tgdb_list *completion_list;
			} update_completions;

			/* header == TGDB_UPDATE_CONSOLE_PROMPT_VALUE */
			struct {
				/* The new prompt GDB has reported */
				const char *prompt_value;
			} update_console_prompt_value;

			/* header == TGDB_QUIT */
			struct {
				struct tgdb_debugger_exit_status *exit_status;
			} quit;

		} choice;
	};

#ifdef __cplusplus
}
#endif

#endif				/* __TGDB_TYPES_H__ */
